﻿package com.zhao.tongcheng.util;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;




public class ClientUtilAndroid 
{
	private String request="";
	private static final int CONNECTION_TIMEOUT = 20000;
	
	
	private static String initHead(String serviceNameName)
	{
		Hashtable<String, Object> ht = new Hashtable<String, Object>();
		Calendar calendar = Calendar.getInstance();
		Date date = calendar.getTime();

		SimpleDateFormat ymdhmsf = new SimpleDateFormat(
				"yyyy-MM-dd HH:mm:ss.SSS");
		String reqTime = ymdhmsf.format(date);

		ht.put("version", "20111128102912"); // 接口协议版本号，详见接口协议文档
		ht.put("accountId", "9760b71e-9369-4f03-a1c6-9f35c4cfadc2"); // API帐户ID(小写)，待申请审批通过后发放
		ht.put("accountKey", "f66eb602596c2627"); // API帐户密钥，待申请审批通过后发放
		ht.put("serviceName", serviceNameName); // 调用接口的方法名称
		ht.put("reqTime", reqTime); // 当前日期
		
		String strRequest = ""; // 请求XML字符串
		strRequest = strRequest
				+ "<?xml version='1.0' encoding='utf-8' standalone='yes'?>";
		strRequest = strRequest + "<request>";
		strRequest = strRequest + "<header>";
		strRequest = strRequest + "<version>" + ht.get("version")
				+ "</version>";
		strRequest = strRequest + "<accountID>" + ht.get("accountId")
				+ "</accountID>";
		strRequest = strRequest + "<serviceName>" + ht.get("serviceName")
				+ "</serviceName>";
		try {
			strRequest = strRequest + "<digitalSign>" + createDigitalSign(ht)
					+ "</digitalSign>";
		} catch (Exception ex) {

			ex.printStackTrace();
		}
		strRequest = strRequest + "<reqTime>" + ht.get("reqTime")
				+ "</reqTime>";
		strRequest = strRequest + "</header>";
		
		return strRequest;
		
	}
	public static String comm(Hashtable<String, Object> params)
	{
		String request="<body>";
		Enumeration<String> keys=params.keys();
		while(keys.hasMoreElements())
		{
			String key=keys.nextElement();
			String value=(String) params.get(key);
			
			if(!value.equals(""))
			{
				//P.p(key+":"+value);
				request=request+"<"+key+">"+params.get(key)+"</"+key+">";
			}
			
		}
		request=request+"</body></request>";
		return request;
	}
	public void test()
	{
		Hashtable<String, Object> ht = new Hashtable<String, Object>(); // 将参数放入Hashtable中，便于操作

		Calendar calendar = Calendar.getInstance();
		Date date = calendar.getTime();

		SimpleDateFormat ymdhmsf = new SimpleDateFormat(
				"yyyy-MM-dd HH:mm:ss.SSS");
		String reqTime = ymdhmsf.format(date);

		ht.put("version", "20111128102912"); // 接口协议版本号，详见接口协议文档
		ht.put("accountId", "9760b71e-9369-4f03-a1c6-9f35c4cfadc2"); // API帐户ID(小写)，待申请审批通过后发放
		ht.put("accountKey", "f66eb602596c2627"); // API帐户密钥，待申请审批通过后发放
		ht.put("serviceName", "DemoFunction"); // 调用接口的方法名称
		ht.put("reqTime", reqTime); // 当前日期
		
		String url = "http://tcopenapitest.17usoft.com/handlers/general/test.ashx"; // 请求URL地址ַ
		System.out.println(comm(ht));
		// body中请求参数
		String param1 = "example";
		int param2 = 1;

		String strRequest = ""; // 请求XML字符串
		strRequest = strRequest
				+ "<?xml version='1.0' encoding='utf-8' standalone='yes'?>";
		strRequest = strRequest + "<request>";
		strRequest = strRequest + "<header>";
		strRequest = strRequest + "<version>" + ht.get("version")
				+ "</version>";
		strRequest = strRequest + "<accountID>" + ht.get("accountId")
				+ "</accountID>";
		strRequest = strRequest + "<serviceName>" + ht.get("serviceName")
				+ "</serviceName>";
		try {
			strRequest = strRequest + "<digitalSign>" + createDigitalSign(ht)
					+ "</digitalSign>";
		} catch (Exception ex) {

			ex.printStackTrace();
		}
		strRequest = strRequest + "<reqTime>" + ht.get("reqTime")
				+ "</reqTime>";
		strRequest = strRequest + "</header>";
		strRequest = strRequest + "<body>";

		// ***将参数param1注释即可看到少传参数返回的错误信息显示***
		strRequest = strRequest + "<param1>" + param1 + "</param1>";

		strRequest = strRequest + "<param2>" + param2 + "</param2>";
		strRequest = strRequest + "</body>";
		strRequest = strRequest + "</request>";

		try {
			String strResponse = callUrl(url, strRequest);
			System.out.println(strResponse);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static String reqesut(String function,String url,Hashtable<String, Object> ht)
	{
		String request=initHead(function);
		
		request=request+comm(ht);
		//P.p(request);
		String strResponse="";
		
		try {
			
			strResponse=httpPost(url,request);
			//P.p(strResponse);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return strResponse;
		
	}
//	public static String comm(Object o,String name)
//	{
//		String request="<body>";
//		//XStream x=new XStream();
//		
//		x.alias(name, o.getClass());
//		request=request+x.toXML(o)+"</body></request>";
//		//request=request+"</body></request>";
//		return request;
//		
//	}
	public static String reqesut(String function,String url,String body)
	{
		String request=initHead(function);
		
		request=request+body;
		//P.p(request);
		String strResponse="";
		
		try {
			
			strResponse=httpPost(url,request);
			//P.p(strResponse);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return strResponse;
		
	}
	public static void main(String[] args) {
//		Hashtable<String, String> ht = new Hashtable<String, String>();
//		ht.put("param1", "example");
//		ht.put("param2", "1");
//		String url = "http://tcopenapitest.17usoft.com/handlers/general/test.ashx";
//		String function="DemoFunction";
//		reqesut(function,url,ht);
		
		try {
			String url="http://un.api.zhuna.cn/api/utf-8/search.asp?cityid=53&pg=1";
		//String s=	callUrl("http://un.api.zhuna.cn/api/utf-8/search.asp?cityid=53&pg=1","");
		//	P.p(s);
//			HttpClient httpClient = new HttpClient();
//			GetMethod httpGet = new GetMethod(url);
//			httpClient.executeMethod(httpGet);
//			String responseData = httpGet.getResponseBodyAsString();
//			 System.out.println(responseData);
			String responseData =httpPost(url,"");
			System.out.println(responseData);
			 //FileUtil.write("zhuna1.xml", responseData);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	public static String httpPost(String url, String queryString) throws Exception {
		StringBuilder responseData =new StringBuilder();
		HttpClient httpClient = new DefaultHttpClient();

		//log.info("QHttpClient httpPost [1] url = "+url);
		HttpPost httpPost = new HttpPost(url);
		ArrayList<NameValuePair> parameters= new ArrayList<NameValuePair>();
		parameters.add(new BasicNameValuePair("Content","application/x-www-form-urlencoded"));
		
		httpPost.getParams().setParameter("Content",
				"application/x-www-form-urlencoded");
		httpPost.getParams().setParameter("http.socket.timeout",
				new Integer(CONNECTION_TIMEOUT));
		if (queryString != null && !queryString.equals("")) {
//			httpPost.setRequestEntity(new ByteArrayEntity(queryString
//					.getBytes()));
			httpPost.setEntity(new ByteArrayEntity(queryString
					.getBytes()));
		}

		try {
			HttpResponse resp = httpClient.execute(httpPost);
			
			if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
				System.err.println("HttpPost Method failed: "
						+ resp.getStatusLine());
				httpPost.abort();
			}else 
			{
				
				HttpEntity entity = resp.getEntity();
				if (entity != null) {
					BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"), 8192);
	    			String line = null;
	    			while ((line = reader.readLine())!= null){
	    				responseData.append(line + "\n");
	    			}
	    			reader.close();
				}
			}
		
			//log.info("QHttpClient httpPost [2] responseData = "+responseData);
		} catch (Exception e) {
			throw new Exception(e);
		} finally {
			//httpPost.
			httpClient.getConnectionManager().shutdown();
		}

		return responseData.toString();
	}
	/**
	 * 数组排序（冒泡排序法）
	 * 
	 * @param originalArray
	 *            待排序字符串数组
	 * @return 经过冒泡排序过的字符串数组
	 */
	public static String[] bubbleSort(String[] originalArray) {
		int i, j; // 交换标志
		String temp;
		Boolean exchange;

		for (i = 0; i < originalArray.length; i++) // 最多做R.Length-1趟排序
		{
			exchange = false; // 本趟排序开始前，交换标志应为假

			for (j = originalArray.length - 2; j >= i; j--) {
				if (originalArray[j + 1].compareTo(originalArray[j]) < 0)// 交换条件
				{
					temp = originalArray[j + 1];
					originalArray[j + 1] = originalArray[j];
					originalArray[j] = temp;

					exchange = true; // 发生了交换，故将交换标志置为真
				}
			}

			if (!exchange) // 本趟排序未发生交换，提前终止算法
			{
				break;
			}
		}

		return originalArray;
	}

	/**
	 * 请求服务器URL地址返回数据POST方式
	 * 
	 * @param url
	 *            远程访问的地址
	 * @param data
	 *            参数
	 * @return // * 远程页面调用结果
	 * @throws Exception
	 */
	public static String callUrl(String url, String data) throws Exception {
		HttpURLConnection conn = null;
		String content = "";

		URL getUrl = new URL(url);
		conn = (HttpURLConnection) getUrl.openConnection();

		// conn.setConnectTimeout(timeOut);
		// conn.setReadTimeout(timeOut);

		conn.setDoOutput(true);
		conn.setDoInput(true);
		conn.setRequestMethod("POST");
		conn.setUseCaches(false);
		conn.setInstanceFollowRedirects(true);
		conn.setRequestProperty("Content-Type", "text/xml");

		byte[] bdata = data.getBytes("utf-8");
		conn.setRequestProperty("Content-Length", String.valueOf(bdata.length));
		conn.connect();
		
		DataOutputStream out = new DataOutputStream(conn.getOutputStream());
		out.write(bdata);
		out.flush();
		out.close();

		BufferedReader reader = new BufferedReader(new InputStreamReader(
				conn.getInputStream()));
		String inputLine;

		while ((inputLine = reader.readLine()) != null) {
			content += inputLine;
		}
		reader.close();
		conn.disconnect();

		return content;
	}

	/**
	 * 创建数字签名
	 * 
	 * @param ht
	 *            存放数字签名参数的Hashtable
	 * @return String DigitalSign
	 * @throws Exception
	 */
	public static String createDigitalSign(Hashtable<String, Object> ht)
			throws Exception {
		if (!ht.containsKey("accountKey")
				|| ht.get("accountKey").toString().trim().length() == 0) {
			throw new Exception("缺少API帐户密钥");
		}
		String accountKey = ht.get("accountKey").toString().trim(); // API帐户密钥

		String version = ""; // 版本号
		String serviceName = ""; // 调用接口的方法名称
		String accountId = ""; // API帐户密钥
		String reqTime = ""; // 当前日期

		if (ht.containsKey("version")) {
			version = (String) ht.get("version");
		}

		if (ht.containsKey("serviceName")) {
			serviceName = (String) ht.get("serviceName");
		}

		if (ht.containsKey("accountId")) {
			accountId = (String) ht.get("accountId");
		}

		if (ht.containsKey("reqTime")) {
			reqTime = (String) ht.get("reqTime");
		}

		String[] originalArray = { "Version=" + version,
				"AccountID=" + accountId, "ServiceName=" + serviceName,
				"ReqTime=" + reqTime };

		String[] sortedArray = bubbleSort(originalArray);

		String digitalSing = getMD5ByArray(sortedArray, accountKey, "utf-8");

		return digitalSing;

	}

	/**
	 * MD5 哈希运算
	 * 
	 * @param input
	 *            待计算MD5哈希值的输入字符串
	 * @param charset
	 *            输入字符串的字符集
	 * @return 输入字符串的MD5哈希值
	 */
	public static String getMD5(String input, String charset) {

		String s = null;
		char hexDigits[] = { // 用来将字节转换成 16 进制表示的字符
		'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
				'e', 'f' };
		try {
			java.security.MessageDigest md = java.security.MessageDigest
					.getInstance("MD5");
			md.update(input.getBytes(charset));
			byte tmp[] = md.digest(); // MD5 的计算结果是一个 128 位的长整数，用字节表示就是 16 个字节

			char str[] = new char[16 * 2]; // 每个字节用 16 进制表示的话，使用两个字符，所以表示成 16
											// 进制需要 32 个字符

			int k = 0; // 表示转换结果中对应的字符位置
			for (int i = 0; i < 16; i++) { // 从第一个字节开始，对 MD5 的每一个字节转换成 16
											// 进制字符的转换

				byte byte0 = tmp[i]; // 取第 i 个字节
				str[k++] = hexDigits[byte0 >>> 4 & 0xf]; // 取字节中高 4 位的数字转换,
															// >>>
															// 为逻辑右移，将符号位一起右移
				str[k++] = hexDigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换
			}
			s = new String(str); // 换后的结果转换为字符串

		} catch (Exception e) {
			e.printStackTrace();
		}
		return s;
	}

	/**
	 * 获取字符数组的MD5哈希值
	 * 
	 * @param sortedArray
	 *            待计算MD5哈希值的输入字符数组
	 * @param key
	 *            密钥
	 * @param charset
	 *            输入字符串的字符集
	 * @return 输入字符数组的MD5哈希值
	 */
	public static String getMD5ByArray(String[] sortedArray, String key,
			String charset) {
		// 构造待md5摘要字符串
		StringBuilder prestr = new StringBuilder();

		for (int i = 0; i < sortedArray.length; i++) {
			if (i == sortedArray.length - 1) {
				prestr.append(sortedArray[i]);
			} else {
				prestr.append(sortedArray[i] + "&");
			}
		}

		prestr.append(key);// 此处key为上面的innerKey

		return getMD5(prestr.toString(), charset);
	}
}
